2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucer_Headers.h"
27 #include "jucer_JucerDocumentHolder.h"
28 #include "jucer_TestComponent.h"
29 #include "jucer_MainWindow.h"
30 #include "../model/jucer_ObjectTypes.h"
31 #include "jucer_ComponentLayoutPanel.h"
32 #include "jucer_PaintRoutinePanel.h"
33 #include "jucer_ResourceEditorPanel.h"
34 #include "../properties/jucer_ComponentTextProperty.h"
35 #include "../properties/jucer_ComponentChoiceProperty.h"
38 //==============================================================================
39 class ExtraMethodsList
: public PropertyComponent
,
44 ExtraMethodsList (JucerDocument
& doc
)
45 : PropertyComponent ("extra callbacks", 250),
48 addAndMakeVisible (listBox
= new ListBox (String::empty
, this));
49 listBox
->setRowHeight (22);
51 document
.addChangeListener (this);
56 document
.removeChangeListener (this);
62 return methods
.size();
65 void paintListBoxItem (int row
, Graphics
& g
, int width
, int height
, bool rowIsSelected
)
67 if (row
< 0 || row
>= getNumRows())
71 g
.fillAll (findColour (TextEditor::highlightColourId
));
73 g
.setColour (Colours::black
);
74 g
.setFont (height
* 0.6f
);
75 g
.drawText (returnValues
[row
] + " " + baseClasses
[row
] + "::" + methods
[row
],
76 30, 0, width
- 32, height
,
77 Justification::centredLeft
, true);
79 getLookAndFeel().drawTickBox (g
, *this, 6, 2, 18, 18, document
.isOptionalMethodEnabled (methods
[row
]), true, false, false);
82 void listBoxItemClicked (int row
, const MouseEvent
& e
)
84 if (row
< 0 || row
>= getNumRows())
88 document
.setOptionalMethodEnabled (methods
[row
],
89 ! document
.isOptionalMethodEnabled (methods
[row
]));
92 void paint (Graphics
& g
)
94 g
.fillAll (Colours::white
);
99 listBox
->setBounds (0, 0, getWidth(), getHeight());
105 returnValues
.clear();
107 initialContents
.clear();
109 document
.getOptionalMethods (baseClasses
, returnValues
, methods
, initialContents
);
111 listBox
->updateContent();
115 void changeListenerCallback (ChangeBroadcaster
*)
121 JucerDocument
& document
;
124 StringArray baseClasses
;
125 StringArray returnValues
;
127 StringArray initialContents
;
131 //==============================================================================
132 class ClassPropertiesPanel
: public Component
,
133 private ChangeListener
136 ClassPropertiesPanel (JucerDocument
& document_
)
137 : document (document_
)
139 addAndMakeVisible (panel1
= new PropertyPanel());
140 addAndMakeVisible (panel2
= new PropertyPanel());
142 Array
<PropertyComponent
*> props
;
143 props
.add (new ComponentClassNameProperty (document_
));
144 props
.add (new ComponentCompNameProperty (document_
));
145 props
.add (new ComponentParentClassesProperty (document_
));
146 props
.add (new ComponentConstructorParamsProperty (document_
));
147 props
.add (new ComponentInitialisersProperty (document_
));
148 props
.add (new ComponentInitialSizeProperty (document_
, true));
149 props
.add (new ComponentInitialSizeProperty (document_
, false));
150 props
.add (new FixedSizeProperty (document_
));
152 panel1
->addSection ("General class settings", props
);
154 Array
<PropertyComponent
*> props2
;
155 props2
.add (new ExtraMethodsList (document_
));
156 panel2
->addSection ("Extra callback methods to generate", props2
);
158 document_
.addExtraClassProperties (panel1
);
160 document_
.addChangeListener (this);
163 ~ClassPropertiesPanel()
165 document
.removeChangeListener (this);
171 int pw
= jmin (getWidth() / 2 - 20, 350);
172 panel1
->setBounds (10, 6, pw
, getHeight() - 12);
173 panel2
->setBounds (panel1
->getRight() + 20, panel1
->getY(), pw
, panel1
->getHeight());
176 void changeListenerCallback (ChangeBroadcaster
*)
178 panel1
->refreshAll();
179 panel2
->refreshAll();
183 JucerDocument
& document
;
185 PropertyPanel
* panel1
;
186 PropertyPanel
* panel2
;
188 //==============================================================================
189 class ComponentClassNameProperty
: public ComponentTextProperty
<Component
>
192 ComponentClassNameProperty (JucerDocument
& document_
)
193 : ComponentTextProperty
<Component
> ("class name", 128, false, 0, document_
)
196 void setText (const String
& newText
) { document
.setClassName (newText
); }
197 const String
getText() const { return document
.getClassName(); }
200 //==============================================================================
201 class ComponentCompNameProperty
: public ComponentTextProperty
<Component
>
204 ComponentCompNameProperty (JucerDocument
& document_
)
205 : ComponentTextProperty
<Component
> ("component name", 200, false, 0, document_
)
208 void setText (const String
& newText
) { document
.setComponentName (newText
); }
209 const String
getText() const { return document
.getComponentName(); }
212 //==============================================================================
213 class ComponentParentClassesProperty
: public ComponentTextProperty
<Component
>
216 ComponentParentClassesProperty (JucerDocument
& document_
)
217 : ComponentTextProperty
<Component
> ("parent classes", 512, false, 0, document_
)
220 void setText (const String
& newText
) { document
.setParentClasses (newText
); }
221 const String
getText() const { return document
.getParentClassString(); }
224 //==============================================================================
225 class ComponentConstructorParamsProperty
: public ComponentTextProperty
<Component
>
228 ComponentConstructorParamsProperty (JucerDocument
& document_
)
229 : ComponentTextProperty
<Component
> ("constructor params", 2048, false, 0, document_
)
232 void setText (const String
& newText
) { document
.setConstructorParams (newText
); }
233 const String
getText() const { return document
.getConstructorParams(); }
236 //==============================================================================
237 class ComponentInitialisersProperty
: public ComponentTextProperty
<Component
>
240 ComponentInitialisersProperty (JucerDocument
& document_
)
241 : ComponentTextProperty
<Component
> ("member intialisers", 2048, true, 0, document_
)
243 preferredHeight
= 24 * 3;
246 void setText (const String
& newText
) { document
.setVariableInitialisers (newText
); }
247 const String
getText() const { return document
.getVariableInitialisers(); }
251 //==============================================================================
252 class ComponentInitialSizeProperty
: public ComponentTextProperty
<Component
>
255 ComponentInitialSizeProperty (JucerDocument
& document_
, const bool isWidth_
)
256 : ComponentTextProperty
<Component
> (isWidth_
? "initial width" : "initial height",
257 10, false, 0, document_
),
261 void setText (const String
& newText
)
264 document
.setInitialSize (newText
.getIntValue(), document
.getInitialHeight());
266 document
.setInitialSize (document
.getInitialWidth(), newText
.getIntValue());
269 const String
getText() const
271 return String (isWidth
? document
.getInitialWidth()
272 : document
.getInitialHeight());
279 //==============================================================================
280 class FixedSizeProperty
: public ComponentChoiceProperty
<Component
>
283 FixedSizeProperty (JucerDocument
& document_
)
284 : ComponentChoiceProperty
<Component
> ("fixed size", 0, document_
)
286 choices
.add ("Resize component to fit workspace");
287 choices
.add ("Keep component size fixed");
290 void setIndex (int newIndex
) { document
.setFixedSize (newIndex
!= 0); }
291 int getIndex() const { return document
.isFixedSize() ? 1 : 0; }
295 //==============================================================================
296 class CodeViewerComp
: public Component
,
297 private ButtonListener
300 //==============================================================================
301 CodeViewerComp (JucerDocument
& document_
)
302 : document (document_
),
303 isHeader (showHeaderFileFirst
)
305 addAndMakeVisible (editor
= new CodeEditorComponent (codeDocument
, &tokeniser
));
307 addAndMakeVisible (switchButton
= new TextButton (String::empty
));
308 switchButton
->addListener (this);
310 setWantsKeyboardFocus (true);
315 showHeaderFileFirst
= isHeader
;
319 void showFile (const bool isHeader_
)
321 isHeader
= isHeader_
;
322 editor
->loadContent (isHeader
? h
: cpp
);
323 switchButton
->setButtonText (isHeader
? "Show .cpp" : "Show .h");
328 editor
->setBounds (4, 4, getWidth() - 8, getHeight() - 8);
329 switchButton
->setBounds (getWidth() - 130, 10, 90, 22);
332 void buttonClicked (Button
*)
334 showFile (! isHeader
);
337 void visibilityChanged()
341 document
.getPreviewFiles (h
, cpp
);
346 //==============================================================================
348 JucerDocument
& document
;
351 CodeDocument codeDocument
;
352 CPlusPlusCodeTokeniser tokeniser
;
353 CodeEditorComponent
* editor
;
354 TextButton
* switchButton
;
356 static bool showHeaderFileFirst
;
359 bool CodeViewerComp::showHeaderFileFirst
= false;
361 static const Colour
tabColour (Colour (0xffc4cdcd));
364 //==============================================================================
365 JucerDocumentHolder::JucerDocumentHolder (JucerDocument
* const document_
)
366 : document (document_
),
371 currentZoomLevel (1.0)
373 jassert (document
!= 0);
377 setSize (document
->getInitialWidth(),
378 document
->getInitialHeight());
380 addAndMakeVisible (tabbedComponent
= new TabbedComponent (TabbedButtonBar::TabsAtRight
));
381 tabbedComponent
->setOutline (0);
383 tabbedComponent
->addTab ("Class", tabColour
, new ClassPropertiesPanel (*document
), true);
385 if (document
->getComponentLayout() != 0)
387 tabbedComponent
->addTab ("Subcomponents", tabColour
,
388 compLayoutPanel
= new ComponentLayoutPanel (*document
, *document
->getComponentLayout()), true);
391 tabbedComponent
->addTab ("Resources", tabColour
, new ResourceEditorPanel (*document
), true);
392 tabbedComponent
->addTab ("Code Preview", tabColour
, new CodeViewerComp (*document
), true);
396 tabbedComponent
->setCurrentTabIndex (0);
398 document
->addChangeListener (this);
401 refreshPropertiesPanel();
403 changeListenerCallback (0);
406 JucerDocumentHolder::~JucerDocumentHolder()
408 tabbedComponent
->clearTabs();
409 deleteAndZero (tabbedComponent
);
413 bool JucerDocumentHolder::close()
415 MainWindow
* const mw
= findParentComponentOfClass ((MainWindow
*) 0);
418 return mw
->closeDocument (this);
424 void JucerDocumentHolder::refreshPropertiesPanel() const
426 if (tabbedComponent
!= 0)
428 for (int i
= tabbedComponent
->getNumTabs(); --i
>= 0;)
430 ComponentLayoutPanel
* layoutPanel
= dynamic_cast <ComponentLayoutPanel
*> (tabbedComponent
->getTabContentComponent (i
));
432 if (layoutPanel
!= 0)
434 if (layoutPanel
->isVisible())
435 layoutPanel
->updatePropertiesList();
439 PaintRoutinePanel
* pr
= dynamic_cast <PaintRoutinePanel
*> (tabbedComponent
->getTabContentComponent (i
));
441 if (pr
!= 0 && pr
->isVisible())
442 pr
->updatePropertiesList();
448 void JucerDocumentHolder::updateTabs()
450 const StringArray
paintRoutineNames (document
->getPaintRoutineNames());
453 for (i
= tabbedComponent
->getNumTabs(); --i
>= 0;)
455 if (dynamic_cast <PaintRoutinePanel
*> (tabbedComponent
->getTabContentComponent (i
)) != 0
456 && ! paintRoutineNames
.contains (tabbedComponent
->getTabNames() [i
]))
458 tabbedComponent
->removeTab (i
);
462 for (i
= 0; i
< document
->getNumPaintRoutines(); ++i
)
464 if (! tabbedComponent
->getTabNames().contains (paintRoutineNames
[i
]))
466 int index
, numPaintRoutinesSeen
= 0;
467 for (index
= 1; index
< tabbedComponent
->getNumTabs(); ++index
)
469 if (dynamic_cast <PaintRoutinePanel
*> (tabbedComponent
->getTabContentComponent (index
)) != 0)
471 if (++numPaintRoutinesSeen
== i
)
479 if (numPaintRoutinesSeen
== 0)
480 index
= document
->getComponentLayout() != 0 ? 2 : 1;
482 tabbedComponent
->addTab (paintRoutineNames
[i
], tabColour
,
483 new PaintRoutinePanel (*document
,
484 *document
->getPaintRoutine (i
),
490 //==============================================================================
491 void JucerDocumentHolder::paint (Graphics
& g
)
493 g
.fillAll (Colours::lightgrey
);
495 if (tabbedComponent
== 0)
497 g
.setColour (Colours::black
);
498 g
.drawText ("no component currently open", 0, 0, getWidth(), getHeight(), Justification::centred
, false);
502 void JucerDocumentHolder::resized()
504 if (tabbedComponent
!= 0)
505 tabbedComponent
->setBounds (0, 0, getWidth(), getHeight());
508 void JucerDocumentHolder::changeListenerCallback (ChangeBroadcaster
*)
510 setName (document
->getClassName());
514 //==============================================================================
515 ApplicationCommandTarget
* JucerDocumentHolder::getNextCommandTarget()
517 return findFirstTargetParentComponent();
520 ComponentLayout
* JucerDocumentHolder::getCurrentLayout() const
522 if (tabbedComponent
!= 0)
524 ComponentLayoutPanel
* panel
= dynamic_cast <ComponentLayoutPanel
*> (tabbedComponent
->getCurrentContentComponent());
527 return &(panel
->getLayout());
533 PaintRoutine
* JucerDocumentHolder::getCurrentPaintRoutine() const
535 if (tabbedComponent
!= 0)
537 PaintRoutinePanel
* panel
= dynamic_cast <PaintRoutinePanel
*> (tabbedComponent
->getCurrentContentComponent());
540 return &(panel
->getPaintRoutine());
546 void JucerDocumentHolder::showLayout()
548 if (getCurrentLayout() == 0 && tabbedComponent
!= 0)
550 for (int i
= 0; i
< tabbedComponent
->getNumTabs(); ++i
)
552 if (dynamic_cast <ComponentLayoutPanel
*> (tabbedComponent
->getTabContentComponent (i
)) != 0)
554 tabbedComponent
->setCurrentTabIndex (i
);
561 void JucerDocumentHolder::showGraphics (PaintRoutine
* routine
)
563 if ((getCurrentPaintRoutine() != routine
|| routine
== 0) && tabbedComponent
!= 0)
565 for (int i
= 0; i
< tabbedComponent
->getNumTabs(); ++i
)
567 PaintRoutinePanel
* pr
= dynamic_cast <PaintRoutinePanel
*> (tabbedComponent
->getTabContentComponent (i
));
569 if (pr
!= 0 && (routine
== &(pr
->getPaintRoutine()) || routine
== 0))
571 tabbedComponent
->setCurrentTabIndex (i
);
578 //==============================================================================
579 void JucerDocumentHolder::setViewportToLastPos (Viewport
* vp
, EditingPanelBase
& editor
)
581 vp
->setViewPosition (lastViewportX
, lastViewportY
);
582 editor
.setZoom (currentZoomLevel
);
585 void JucerDocumentHolder::storeLastViewportPos (Viewport
* vp
, EditingPanelBase
& editor
)
587 lastViewportX
= vp
->getViewPositionX();
588 lastViewportY
= vp
->getViewPositionY();
590 currentZoomLevel
= editor
.getZoom();
593 void JucerDocumentHolder::setZoom (double scale
)
595 scale
= jlimit (1.0 / 4.0, 32.0, scale
);
597 if (tabbedComponent
!= 0)
599 EditingPanelBase
* panel
= dynamic_cast <EditingPanelBase
*> (tabbedComponent
->getCurrentContentComponent());
602 panel
->setZoom (scale
);
606 double JucerDocumentHolder::getZoom() const
608 if (tabbedComponent
!= 0)
610 EditingPanelBase
* panel
= dynamic_cast <EditingPanelBase
*> (tabbedComponent
->getCurrentContentComponent());
613 return panel
->getZoom();
619 void JucerDocumentHolder::addElement (const int index
)
621 if (tabbedComponent
!= 0)
623 PaintRoutinePanel
* const panel
= dynamic_cast <PaintRoutinePanel
*> (tabbedComponent
->getCurrentContentComponent());
627 PaintRoutine
* const currentPaintRoutine
= & (panel
->getPaintRoutine());
628 const Rectangle
<int> area (panel
->getComponentArea());
630 document
->getUndoManager().beginNewTransaction();
632 PaintElement
* e
= ObjectTypes::createNewElement (index
, currentPaintRoutine
);
634 e
->setInitialBounds (area
.getWidth(), area
.getHeight());
636 e
= currentPaintRoutine
->addNewElement (e
, -1, true);
640 const int randomness
= jmin (80, area
.getWidth() / 2, area
.getHeight() / 2);
641 int x
= area
.getX() + area
.getWidth() / 2 + Random::getSystemRandom().nextInt (randomness
) - randomness
/ 2;
642 int y
= area
.getY() + area
.getHeight() / 2 + Random::getSystemRandom().nextInt (randomness
) - randomness
/ 2;
643 x
= document
->snapPosition (x
);
644 y
= document
->snapPosition (y
);
646 panel
->xyToTargetXY (x
, y
);
648 Rectangle
<int> r (e
->getCurrentBounds (area
));
649 r
.setPosition (x
, y
);
650 e
->setCurrentBounds (r
, area
, true);
652 currentPaintRoutine
->getSelectedElements().selectOnly (e
);
655 document
->getUndoManager().beginNewTransaction();
660 void JucerDocumentHolder::addComponent (const int index
)
662 if (tabbedComponent
!= 0)
665 ComponentLayoutPanel
* const panel
= dynamic_cast <ComponentLayoutPanel
*> (tabbedComponent
->getCurrentContentComponent());
669 const Rectangle
<int> area (panel
->getComponentArea());
671 document
->getUndoManager().beginNewTransaction ("Add new " + ObjectTypes::componentTypeHandlers
[index
]->getTypeName());
673 const int randomness
= jmin (80, area
.getWidth() / 2, area
.getHeight() / 2);
674 int x
= area
.getWidth() / 2 + Random::getSystemRandom().nextInt (randomness
) - randomness
/ 2;
675 int y
= area
.getHeight() / 2 + Random::getSystemRandom().nextInt (randomness
) - randomness
/ 2;
676 x
= document
->snapPosition (x
);
677 y
= document
->snapPosition (y
);
679 panel
->xyToTargetXY (x
, y
);
681 Component
* newOne
= panel
->getLayout().addNewComponent (ObjectTypes::componentTypeHandlers
[index
], x
, y
);
684 panel
->getLayout().getSelectedSet().selectOnly (newOne
);
686 document
->getUndoManager().beginNewTransaction();
691 //==============================================================================
692 bool JucerDocumentHolder::isSomethingSelected() const
694 ComponentLayout
* layout
= getCurrentLayout();
697 return layout
->getSelectedSet().getNumSelected() > 0;
699 PaintRoutine
* routine
= getCurrentPaintRoutine();
702 return routine
->getSelectedElements().getNumSelected() > 0;
707 //==============================================================================
708 void JucerDocumentHolder::getAllCommands (Array
<CommandID
>& commands
)
710 const CommandID ids
[] =
722 CommandIDs::bringBackLostItems
,
723 CommandIDs::enableSnapToGrid
,
724 CommandIDs::showGrid
,
725 CommandIDs::editCompLayout
,
726 CommandIDs::editCompGraphics
,
729 CommandIDs::zoomNormal
,
730 CommandIDs::spaceBarDrag
,
731 CommandIDs::compOverlay0
,
732 CommandIDs::compOverlay33
,
733 CommandIDs::compOverlay66
,
734 CommandIDs::compOverlay100
,
735 StandardApplicationCommandIDs::cut
,
736 StandardApplicationCommandIDs::copy
,
737 StandardApplicationCommandIDs::paste
,
738 StandardApplicationCommandIDs::del
,
739 StandardApplicationCommandIDs::selectAll
,
740 StandardApplicationCommandIDs::deselectAll
743 commands
.addArray (ids
, numElementsInArray (ids
));
746 for (i
= 0; i
< ObjectTypes::numComponentTypes
; ++i
)
747 commands
.add (CommandIDs::newComponentBase
+ i
);
749 for (i
= 0; i
< ObjectTypes::numElementTypes
; ++i
)
750 commands
.add (CommandIDs::newElementBase
+ i
);
753 void JucerDocumentHolder::getCommandInfo (const CommandID commandID
, ApplicationCommandInfo
& result
)
755 ComponentLayout
* const currentLayout
= getCurrentLayout();
756 PaintRoutine
* const currentPaintRoutine
= getCurrentPaintRoutine();
758 const int cmd
= ModifierKeys::commandModifier
;
759 const int shift
= ModifierKeys::shiftModifier
;
761 if (commandID
>= CommandIDs::newComponentBase
762 && commandID
< CommandIDs::newComponentBase
+ ObjectTypes::numComponentTypes
)
764 const int index
= commandID
- CommandIDs::newComponentBase
;
766 result
.setInfo ("New " + ObjectTypes::componentTypeHandlers
[index
]->getTypeName(),
767 "Creates a new " + ObjectTypes::componentTypeHandlers
[index
]->getTypeName(),
768 CommandCategories::editing
, 0);
772 if (commandID
>= CommandIDs::newElementBase
773 && commandID
< CommandIDs::newElementBase
+ ObjectTypes::numElementTypes
)
775 const int index
= commandID
- CommandIDs::newElementBase
;
777 result
.setInfo (String ("New ") + ObjectTypes::elementTypeNames
[index
],
778 String ("Adds a new ") + ObjectTypes::elementTypeNames
[index
],
779 CommandCategories::editing
, 0);
781 result
.setActive (currentPaintRoutine
!= 0);
787 case CommandIDs::close
:
788 result
.setInfo ("Close",
789 "Closes the component that's currently being edited.",
790 CommandCategories::general
, 0);
793 case CommandIDs::save
:
794 result
.setInfo ("Save",
795 "Saves the current component.",
796 CommandCategories::general
, 0);
798 result
.defaultKeypresses
.add (KeyPress ('s', cmd
, 0));
802 case CommandIDs::saveAs
:
803 result
.setInfo ("Save As...",
804 "Saves the current component to a specified file.",
805 CommandCategories::general
, 0);
806 result
.defaultKeypresses
.add (KeyPress ('s', cmd
| shift
, 0));
809 case CommandIDs::undo
:
810 result
.setInfo ("Undo",
811 "Undoes the last operation.",
812 CommandCategories::editing
, 0);
813 result
.setActive (document
->getUndoManager().canUndo());
814 result
.defaultKeypresses
.add (KeyPress ('z', cmd
, 0));
817 case CommandIDs::redo
:
818 result
.setInfo ("Redo",
819 "Redoes the last operation.",
820 CommandCategories::editing
, 0);
821 result
.setActive (document
->getUndoManager().canRedo());
822 result
.defaultKeypresses
.add (KeyPress ('z', cmd
| shift
, 0));
823 result
.defaultKeypresses
.add (KeyPress ('y', cmd
, 0));
826 case CommandIDs::toFront
:
827 result
.setInfo ("Bring to front",
828 "Brings the currently selected component to the front.",
829 CommandCategories::editing
, 0);
830 result
.setActive (isSomethingSelected());
831 result
.defaultKeypresses
.add (KeyPress ('f', cmd
, 0));
834 case CommandIDs::toBack
:
835 result
.setInfo ("Send to back",
836 "Sends the currently selected component to the back.",
837 CommandCategories::editing
, 0);
838 result
.setActive (isSomethingSelected());
839 result
.defaultKeypresses
.add (KeyPress ('b', cmd
, 0));
842 case CommandIDs::group
:
843 result
.setInfo ("Group selected items",
844 "Turns the currently selected elements into a single group object.",
845 CommandCategories::editing
, 0);
846 result
.setActive (currentPaintRoutine
!= 0
847 && currentPaintRoutine
->getSelectedElements().getNumSelected() > 1);
848 result
.defaultKeypresses
.add (KeyPress ('k', cmd
, 0));
851 case CommandIDs::ungroup
:
852 result
.setInfo ("Ungroup selected items",
853 "Turns the currently selected elements into a single group object.",
854 CommandCategories::editing
, 0);
855 result
.setActive (currentPaintRoutine
!= 0
856 && currentPaintRoutine
->getSelectedElements().getNumSelected() == 1
857 && currentPaintRoutine
->getSelectedElements().getSelectedItem (0)->getTypeName() == "Group");
858 result
.defaultKeypresses
.add (KeyPress ('k', cmd
| shift
, 0));
861 case CommandIDs::test
:
862 result
.setInfo ("Test component...",
863 "Runs the current component interactively.",
864 CommandCategories::view
, 0);
865 result
.defaultKeypresses
.add (KeyPress ('t', cmd
, 0));
868 case CommandIDs::enableSnapToGrid
:
869 result
.setInfo ("Enable snap-to-grid",
870 "Toggles whether components' positions are aligned to a grid.",
871 CommandCategories::view
, 0);
872 result
.setTicked (document
->isSnapActive (false));
873 result
.defaultKeypresses
.add (KeyPress ('g', cmd
, 0));
876 case CommandIDs::showGrid
:
877 result
.setInfo ("Show snap-to-grid",
878 "Toggles whether the snapping grid is displayed on-screen.",
879 CommandCategories::view
, 0);
880 result
.setTicked (document
->isSnapShown());
881 result
.defaultKeypresses
.add (KeyPress ('g', cmd
| shift
, 0));
884 case CommandIDs::editCompLayout
:
885 result
.setInfo ("Edit sub-component layout",
886 "Switches to the sub-component editor view.",
887 CommandCategories::view
, 0);
888 result
.setActive (tabbedComponent
!= 0);
889 result
.setTicked (currentLayout
!= 0);
890 result
.defaultKeypresses
.add (KeyPress ('n', cmd
, 0));
893 case CommandIDs::editCompGraphics
:
894 result
.setInfo ("Edit background graphics",
895 "Switches to the background graphics editor view.",
896 CommandCategories::view
, 0);
897 result
.setActive (tabbedComponent
!= 0);
898 result
.setTicked (currentPaintRoutine
!= 0);
899 result
.defaultKeypresses
.add (KeyPress ('m', cmd
, 0));
902 case CommandIDs::bringBackLostItems
:
903 result
.setInfo ("Retrieve offscreen items",
904 "Moves any items that are lost beyond the edges of the screen back to the centre.",
905 CommandCategories::editing
, 0);
906 result
.setActive (currentPaintRoutine
!= 0 || currentLayout
!= 0);
907 result
.defaultKeypresses
.add (KeyPress ('m', cmd
, 0));
910 case CommandIDs::zoomIn
:
911 result
.setInfo ("Zoom in",
912 "Zooms in on the current component.",
913 CommandCategories::editing
, 0);
914 result
.setActive (currentPaintRoutine
!= 0 || currentLayout
!= 0);
915 result
.defaultKeypresses
.add (KeyPress (']', cmd
, 0));
918 case CommandIDs::zoomOut
:
919 result
.setInfo ("Zoom out",
920 "Zooms out on the current component.",
921 CommandCategories::editing
, 0);
922 result
.setActive (currentPaintRoutine
!= 0 || currentLayout
!= 0);
923 result
.defaultKeypresses
.add (KeyPress ('[', cmd
, 0));
926 case CommandIDs::zoomNormal
:
927 result
.setInfo ("Zoom to 100%",
928 "Restores the zoom level to normal.",
929 CommandCategories::editing
, 0);
930 result
.setActive (currentPaintRoutine
!= 0 || currentLayout
!= 0);
931 result
.defaultKeypresses
.add (KeyPress ('1', cmd
, 0));
934 case CommandIDs::spaceBarDrag
:
935 result
.setInfo ("Scroll while dragging mouse",
936 "When held down, this key lets you scroll around by dragging with the mouse.",
937 CommandCategories::view
, ApplicationCommandInfo::wantsKeyUpDownCallbacks
);
938 result
.setActive (currentPaintRoutine
!= 0 || currentLayout
!= 0);
939 result
.defaultKeypresses
.add (KeyPress (KeyPress::spaceKey
, 0, 0));
942 case CommandIDs::compOverlay0
:
943 case CommandIDs::compOverlay33
:
944 case CommandIDs::compOverlay66
:
945 case CommandIDs::compOverlay100
:
947 int amount
= 0, num
= 0;
949 if (commandID
== CommandIDs::compOverlay33
)
954 else if (commandID
== CommandIDs::compOverlay66
)
959 else if (commandID
== CommandIDs::compOverlay100
)
965 result
.defaultKeypresses
.add (KeyPress ('2' + num
, cmd
, 0));
967 int currentAmount
= 0;
968 if (document
->getComponentOverlayOpacity() > 0.9f
)
970 else if (document
->getComponentOverlayOpacity() > 0.6f
)
972 else if (document
->getComponentOverlayOpacity() > 0.3f
)
975 result
.setInfo (commandID
== CommandIDs::compOverlay0
976 ? "No component overlay"
977 : "Overlay with opacity of " + String (amount
) + "%",
978 "Changes the opacity of the components that are shown over the top of the graphics editor.",
979 CommandCategories::view
, 0);
980 result
.setActive (currentPaintRoutine
!= 0 && document
->getComponentLayout() != 0);
981 result
.setTicked (amount
== currentAmount
);
985 case StandardApplicationCommandIDs::cut
:
986 result
.setInfo ("Cut",
987 "Copies the currently selected components to the clipboard and deletes them.",
988 CommandCategories::editing
, 0);
989 result
.setActive (isSomethingSelected());
990 result
.defaultKeypresses
.add (KeyPress ('x', cmd
, 0));
993 case StandardApplicationCommandIDs::copy
:
994 result
.setInfo ("Copy",
995 "Copies the currently selected components to the clipboard.",
996 CommandCategories::editing
, 0);
997 result
.setActive (isSomethingSelected());
998 result
.defaultKeypresses
.add (KeyPress ('c', cmd
, 0));
1001 case StandardApplicationCommandIDs::paste
:
1003 result
.setInfo ("Paste",
1004 "Pastes any components from the clipboard.",
1005 CommandCategories::editing
, 0);
1006 result
.defaultKeypresses
.add (KeyPress ('v', cmd
, 0));
1008 bool canPaste
= false;
1009 XmlDocument
clip (SystemClipboard::getTextFromClipboard());
1010 XmlElement
* const doc
= clip
.getDocumentElement (true);
1014 if (doc
->hasTagName (ComponentLayout::clipboardXmlTag
))
1015 canPaste
= (currentLayout
!= 0);
1016 else if (doc
->hasTagName (PaintRoutine::clipboardXmlTag
))
1017 canPaste
= (currentPaintRoutine
!= 0);
1022 result
.setActive (canPaste
);
1027 case StandardApplicationCommandIDs::del
:
1028 result
.setInfo ("Delete",
1029 "Deletes any selected components.",
1030 CommandCategories::editing
, 0);
1031 result
.setActive (isSomethingSelected());
1032 result
.defaultKeypresses
.add (KeyPress (KeyPress::deleteKey
, 0, 0));
1033 result
.defaultKeypresses
.add (KeyPress (KeyPress::backspaceKey
, 0, 0));
1036 case StandardApplicationCommandIDs::selectAll
:
1037 result
.setInfo ("Select All",
1038 "Selects all of whatever item is currently selected.",
1039 CommandCategories::editing
, 0);
1040 result
.setActive (currentPaintRoutine
!= 0 || currentLayout
!= 0);
1041 result
.defaultKeypresses
.add (KeyPress ('a', cmd
, 0));
1044 case StandardApplicationCommandIDs::deselectAll
:
1045 result
.setInfo ("Deselect All",
1046 "Deselects whatever is currently selected.",
1047 CommandCategories::editing
, 0);
1048 result
.setActive (currentPaintRoutine
!= 0 || currentLayout
!= 0);
1049 result
.defaultKeypresses
.add (KeyPress ('d', cmd
, 0));
1057 bool JucerDocumentHolder::perform (const InvocationInfo
& info
)
1059 ComponentLayout
* const currentLayout
= getCurrentLayout();
1060 PaintRoutine
* const currentPaintRoutine
= getCurrentPaintRoutine();
1062 document
->getUndoManager().beginNewTransaction();
1064 if (info
.commandID
>= CommandIDs::newComponentBase
1065 && info
.commandID
< CommandIDs::newComponentBase
+ ObjectTypes::numComponentTypes
)
1067 addComponent (info
.commandID
- CommandIDs::newComponentBase
);
1071 if (info
.commandID
>= CommandIDs::newElementBase
1072 && info
.commandID
< CommandIDs::newElementBase
+ ObjectTypes::numElementTypes
)
1074 addElement (info
.commandID
- CommandIDs::newElementBase
);
1078 switch (info
.commandID
)
1080 case CommandIDs::close
:
1082 // (this comp will now be deleted)
1085 case CommandIDs::save
:
1086 document
->save (true, true);
1089 case CommandIDs::saveAs
:
1090 document
->saveAsInteractive (true);
1093 case CommandIDs::undo
:
1094 document
->getUndoManager().undo();
1095 document
->dispatchPendingMessages();
1098 case CommandIDs::redo
:
1099 document
->getUndoManager().redo();
1100 document
->dispatchPendingMessages();
1103 case CommandIDs::test
:
1104 TestComponent::showInDialogBox (*document
);
1107 case CommandIDs::enableSnapToGrid
:
1108 document
->setSnappingGrid (document
->getSnappingGridSize(),
1109 ! document
->isSnapActive (false),
1110 document
->isSnapShown());
1113 case CommandIDs::showGrid
:
1114 document
->setSnappingGrid (document
->getSnappingGridSize(),
1115 document
->isSnapActive (false),
1116 ! document
->isSnapShown());
1119 case CommandIDs::editCompLayout
:
1123 case CommandIDs::editCompGraphics
:
1127 case CommandIDs::zoomIn
:
1128 setZoom (getZoom() * 2.0);
1131 case CommandIDs::zoomOut
:
1132 setZoom (getZoom() / 2.0);
1135 case CommandIDs::zoomNormal
:
1139 case CommandIDs::spaceBarDrag
:
1141 EditingPanelBase
* panel
= dynamic_cast <EditingPanelBase
*> (tabbedComponent
->getCurrentContentComponent());
1144 panel
->dragKeyHeldDown (info
.isKeyDown
);
1149 case CommandIDs::compOverlay0
:
1150 case CommandIDs::compOverlay33
:
1151 case CommandIDs::compOverlay66
:
1152 case CommandIDs::compOverlay100
:
1156 if (info
.commandID
== CommandIDs::compOverlay33
)
1158 else if (info
.commandID
== CommandIDs::compOverlay66
)
1160 else if (info
.commandID
== CommandIDs::compOverlay100
)
1163 document
->setComponentOverlayOpacity (amount
* 0.01f
);
1167 case CommandIDs::bringBackLostItems
:
1169 EditingPanelBase
* panel
= dynamic_cast <EditingPanelBase
*> (tabbedComponent
->getCurrentContentComponent());
1173 int w
= panel
->getComponentArea().getWidth();
1174 int h
= panel
->getComponentArea().getHeight();
1176 if (currentPaintRoutine
!= 0)
1177 currentPaintRoutine
->bringLostItemsBackOnScreen (panel
->getComponentArea());
1178 else if (currentLayout
!= 0)
1179 currentLayout
->bringLostItemsBackOnScreen (w
, h
);
1185 case CommandIDs::toFront
:
1186 if (currentLayout
!= 0)
1187 currentLayout
->selectedToFront();
1188 else if (currentPaintRoutine
!= 0)
1189 currentPaintRoutine
->selectedToFront();
1193 case CommandIDs::toBack
:
1194 if (currentLayout
!= 0)
1195 currentLayout
->selectedToBack();
1196 else if (currentPaintRoutine
!= 0)
1197 currentPaintRoutine
->selectedToBack();
1201 case CommandIDs::group
:
1202 if (currentPaintRoutine
!= 0)
1203 currentPaintRoutine
->groupSelected();
1206 case CommandIDs::ungroup
:
1207 if (currentPaintRoutine
!= 0)
1208 currentPaintRoutine
->ungroupSelected();
1211 case StandardApplicationCommandIDs::cut
:
1212 if (currentLayout
!= 0)
1214 currentLayout
->copySelectedToClipboard();
1215 currentLayout
->deleteSelected();
1217 else if (currentPaintRoutine
!= 0)
1219 currentPaintRoutine
->copySelectedToClipboard();
1220 currentPaintRoutine
->deleteSelected();
1225 case StandardApplicationCommandIDs::copy
:
1226 if (currentLayout
!= 0)
1227 currentLayout
->copySelectedToClipboard();
1228 else if (currentPaintRoutine
!= 0)
1229 currentPaintRoutine
->copySelectedToClipboard();
1233 case StandardApplicationCommandIDs::paste
:
1235 XmlDocument
clip (SystemClipboard::getTextFromClipboard());
1236 XmlElement
* const doc
= clip
.getDocumentElement (true);
1240 if (doc
->hasTagName (ComponentLayout::clipboardXmlTag
))
1242 if (currentLayout
!= 0)
1243 currentLayout
->paste();
1245 else if (doc
->hasTagName (PaintRoutine::clipboardXmlTag
))
1247 if (currentPaintRoutine
!= 0)
1248 currentPaintRoutine
->paste();
1256 case StandardApplicationCommandIDs::del
:
1257 if (currentLayout
!= 0)
1258 currentLayout
->deleteSelected();
1259 else if (currentPaintRoutine
!= 0)
1260 currentPaintRoutine
->deleteSelected();
1264 case StandardApplicationCommandIDs::selectAll
:
1265 if (currentLayout
!= 0)
1266 currentLayout
->selectAll();
1267 else if (currentPaintRoutine
!= 0)
1268 currentPaintRoutine
->selectAll();
1271 case StandardApplicationCommandIDs::deselectAll
:
1272 if (currentLayout
!= 0)
1274 currentLayout
->getSelectedSet().deselectAll();
1276 else if (currentPaintRoutine
!= 0)
1278 currentPaintRoutine
->getSelectedElements().deselectAll();
1279 currentPaintRoutine
->getSelectedPoints().deselectAll();
1288 document
->getUndoManager().beginNewTransaction();
1292 JucerDocumentHolder
* JucerDocumentHolder::getActiveDocumentHolder()
1294 ApplicationCommandInfo
info (0);
1295 ApplicationCommandTarget
* target
= commandManager
->getTargetForCommand (CommandIDs::close
, info
);
1297 return dynamic_cast <JucerDocumentHolder
*> (target
);
1300 const Image
JucerDocumentHolder::createComponentLayerSnapshot() const
1302 if (compLayoutPanel
!= 0)
1303 return compLayoutPanel
->createComponentSnapshot();